package com.iotechn.unimall.launcher.controller;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.iotechn.unimall.core.util.GeneratorUtil;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping({"/upload"})
public class FileUploadController implements InitializingBean {
    private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);

    @Value("${oss.aliyun.oss.accessId}")
    private String accessId;

    @Value("${oss.aliyun.oss.accessKey}")
    private String accessKey;

    @Value("${oss.aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${oss.aliyun.oss.bucket}")
    private String bucket;

    @Value("${oss.aliyun.oss.dir}")
    private String dir;

    @Value("${oss.aliyun.oss.callbackUrl}")
    private String callbackUrl;

    @Value("${oss.aliyun.oss.basekUrl}")
    private String baseUrl;

    @Autowired
    private OSSClient ossClient;

    private String host;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.host = "http://" + this.bucket + "." + this.endpoint;
    }

    @RequestMapping(method = {RequestMethod.GET})
    public void upload(HttpServletRequest request, HttpServletResponse response) {
        try {
            long expireTime = 30L;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000L;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem("content-length-range", 0L, 1048576000L);
            policyConds.addConditionItem(MatchMode.StartWith, "key", this.dir);
            String postPolicy = this.ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = this.ossClient.calculatePostSignature(postPolicy);
            JSONObject respJsonObj = new JSONObject();
            respJsonObj.put("accessid", this.accessId);
            respJsonObj.put("policy", encodedPolicy);
            respJsonObj.put("signature", postSignature);
            respJsonObj.put("dir", this.dir);
            respJsonObj.put("host", this.host);
            respJsonObj.put("expire", String.valueOf(expireEndTime / 1000L));
            JSONObject jasonCallback = new JSONObject();
            jasonCallback.put("callbackUrl", this.callbackUrl);
            jasonCallback.put("callbackBody", "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
            respJsonObj.put("callback", base64CallbackBody);
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
            respJsonObj.put("code", Integer.valueOf(200));
            respJsonObj.put("baseUrl", this.baseUrl);
            response(request, response, respJsonObj.toJSONString());
        } catch (Exception e) {
            logger.error("[上传签名]异常", e);
        }
    }

    @PostMapping({"/admin"})
    @ResponseBody
    public Object create(@RequestParam("file") MultipartFile file) throws IOException {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(file.getSize());
        objectMetadata.setContentType(file.getContentType());
        String ext = FilenameUtils.getExtension(file.getOriginalFilename());
        String uuid = GeneratorUtil.genFileName();
        PutObjectRequest putObjectRequest = new PutObjectRequest(this.bucket, "bg/" + uuid + "." + ext, file.getInputStream(), objectMetadata);
        this.ossClient.putObject(putObjectRequest);
        Map<String, Object> data = new HashMap<>();
        data.put("url", this.baseUrl + "bg/" + uuid + "." + ext);
        data.put("errno", Integer.valueOf(200));
        data.put("errmsg", "成功");
        return data;
    }

    @RequestMapping(method = {RequestMethod.POST})
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Map<String, String[]> parameterMap = request.getParameterMap();
        JSONObject responseJson = new JSONObject();
        responseJson.put("code", Integer.valueOf(200));
        for (String key : parameterMap.keySet()) {
            responseJson.put(key, ((String[])parameterMap.get(key))[0]);
        }
        response(request, response, responseJson.toJSONString(), 200);
    }

    private void response(HttpServletRequest request, HttpServletResponse response, String results, int status) throws IOException {
        String callbackFunName = request.getParameter("callback");
        response.addHeader("Content-Length", String.valueOf(results.length()));
        if (callbackFunName == null || callbackFunName.equalsIgnoreCase("")) {
            response.getWriter().println(results);
        } else {
            response.getWriter().println(callbackFunName + "( " + results + " )");
        }
        response.setStatus(status);
        response.flushBuffer();
    }

    private void response(HttpServletRequest request, HttpServletResponse response, String results) throws IOException {
        String callbackFunName = request.getParameter("callback");
        if (callbackFunName == null || callbackFunName.equalsIgnoreCase("")) {
            response.getWriter().println(results);
        } else {
            response.getWriter().println(callbackFunName + "( " + results + " )");
        }
        response.setStatus(200);
        response.flushBuffer();
    }
}
